package com.cci.kangdao.service.impl;

import com.cci.kangdao.common.RedisKeys;
import com.cci.kangdao.common.type.OverTimeType;
import com.cci.kangdao.crmapi.CRMApiUtils;
import com.cci.kangdao.crmapi.CRMResponeEntity;
import com.cci.kangdao.crmapi.CRMServiceApi;
import com.cci.kangdao.dao.*;
import com.cci.kangdao.dao.model.UserT;
import com.cci.kangdao.dao.model.WorkOrderT;
import com.cci.kangdao.dto.request.AccountEngineRelaRequest;
import com.cci.kangdao.entity.AgreementSigned;
import com.cci.kangdao.redis.RedisClientUtils;
import com.cci.kangdao.service.AsyncCrmService;
import com.cci.kangdao.service.DBUMessageService;
import com.cci.kangdao.service.NoticeService;
import com.cci.kangdao.service.RemindTaskService;
import com.cci.kangdao.utilTool.*;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author William Du
 * @date 2020/3/30
 */
@Service
public class AsyncCrmServiceImpl implements AsyncCrmService {
    private Logger log = Logger.getLogger(this.getClass().getName());
    @Resource
    private CRMServiceApi crmServiceApi;
    @Resource
    private NoticeService noticeService;
    @Resource
    public RemindTaskService remindTaskService;
    @Resource
    private OverTimeNotifyAreaEngineerDao overTimeNotifyAreaEngineerDao;
    @Resource
    private WorkOrderOperatorRelationDao workOrderOperatorRelationDao;
    @Autowired
    private LoginDao loginDao;
    @Resource
    private NotifyRecordTDao notifyRecordTDao;
    @Resource
    private CRMPlatformServiceDao crmPlatformServiceDao;
    @Resource
    private WorkOrderTDao workOrderTDao;
    @Resource
    private RedisClientUtils redisClientUtils;
    @Resource
    CustomerEngineRelDao customerEngineRelDao;
    @Resource
    private DBURemindTaskTDao dbuRemindTaskTDao;
    @Resource
    private DBUMessageService dbuMessageService;
    @Resource
    private PositionUserTDao positionUserTDao;
    @Resource
    private UserTDao userTDao;

    private final static String VR_TIMEOUT_TEXT = "【请及时登录APP更新或查看超时原因】";

    @Override
    public void syncStatusToCCEC(String orderNo, Integer status) {
        Map<String, Object> orderMap = crmPlatformServiceDao.getOldOrderInfoByOrderNo(orderNo);
        if (MapUtils.isNotEmpty(orderMap)) {
            if (status.equals(Dictionaries.OrderStatus_06.getIndex())) {
                Map<String, Object> parameter = new HashMap<>();
                parameter.put("orderNo", orderNo);
                parameter.put("CCSSComplainerOrderNo", MapUtils.getString(orderMap, "OrderNoCrm", ""));
                parameter.put("CCSSOrderNo", MapUtils.getString(orderMap, "CCSSOrderNo", ""));
                parameter.put("billStatus", Dictionaries.OrderStatus_06.getIndex());
                parameter.put("needGoOut", MapUtils.getInteger(orderMap, "IsOutSide", 0));
                parameter.put("directorName", "系统");
                parameter.put("directorPhone", "");
                parameter.put("actionTime", LocalTimeUtil.getRealCurrentTime());
                parameter.put("serviceCar", MapUtils.getString(orderMap, "ServiceCar", ""));
                crmServiceApi.syncOrderStatusToCrm("CCEC", crmPlatformServiceDao, redisClientUtils, parameter,null);
            }
        }
    }

    @Override
    public void workOrderUnfinishedOvertime(String systemTime) {
        log.info("DBU-workOrderUnfinishedOvertime方法--开始" + systemTime);

        /**
         * 查询  服务工单当前处于未完成状态
         */
        List<Map<String, Object>> workOrderList = dbuRemindTaskTDao.selectWorkOrderWithUnfinished(systemTime);
        if (CollectionUtils.isNotEmpty(workOrderList)) {
            // 拼装超时未完成工单未通知信息列表
            List<Map<String, Object>> overTimeOrderList = new ArrayList<>();
            /**
             * 修改前针对的时间段为 4、8、24、48
             * 修改后针对的时间段为4、6、12、24、48、72
             *
             * 2022-12-02 修改后针对的时间段为4、6、12、24、48、72、96、360
             */
            for (Map<String, Object> orderMap : workOrderList) {

                Integer function = 0;
                // overTime是系统的当前时间-工单的创建时间  单位：分
                Long overTime = MapUtils.getLong(orderMap, "OverTime", 0L);


                String MarketType = MapUtils.getString(orderMap, "MarketType");
                Long orderId = MapUtils.getLong(orderMap, "ID");
                Integer orderStatus = MapUtils.getInteger(orderMap, "OrderStatus");

                /**
                 *  4小时之内如果未完成，不做处理
                 */
                if (overTime < 4 * 60) {
                    // 小于4小时
                    continue;
                }

                /**
                 *  4-6小时之内(包含4小时)时做处理
                 */
                else if (overTime >= 4 * 60 && overTime < 6 * 60) {
                    // 4小时未完成
                    function = 21;
                }

                /**
                 *  6-12小时之内(包含6小时)时做处理
                 */
                else if (overTime >= 6 * 60 && overTime < 12 * 60) {
                    // 6小时未完成
                    function = 22;
                }

                /**
                 *  12-24小时之内(包含12小时)时做处理
                 */
                else if (overTime >= 12 * 60 && overTime < 24 * 60) {
                    // 12小时未完成
                    function = 23;
                }


                /**
                 *  24-48小时之内(包含24小时)时做处理
                 */
                else if (overTime >= 24 * 60 && overTime < 48 * 60) {
                    // 24小时未完成
                    function = 14;

                    /**
                     *  48-72小时之内(包含48小时)时做处理
                     */
                } else if (overTime >= 48 * 60 && overTime < 72 * 60) {
                    // 48小时未完成
                    function = 15;
                }

                /**
                 *  72-96小时之内(包含72小时)时做处理
                 */
                else if (overTime >= 72 * 60 && overTime < 96 * 60) {
                    // 72小时未完成
                    function = 24;

                    /**
                     * 96 - 360小时内（包含96小时）时做处理
                      */
                } else if(overTime >= 96 * 60 && overTime < 360 * 60){
                    // 96小时未完成
                    function = 25;


                    /**
                     * 大于360小时（包含360小时）时做处理
                     */
                }else if(overTime >= 360 * 60){
                    // 360小时未完成
                    function = 26;
                } else {
                    continue;
                }

                /**
                 * 2021-04-16 新的服务工单未完成超时增加了6h、12h超时时间段(同时作废了8h时间段)
                 * 校验当前服务工单是否已经发送过function类型的消息
                 * 比如
                 *	Function	21	未完成工单4小时提醒
                 *	Function	22	未完成工单6小时提醒
                 *	Function	23	未完成工单12小时提醒
                 *  Function	14	未完成工单24小时提醒
                 *	Function	15	未完成工单48小时提醒
                 *	Function	24	未完成工单72小时提醒
                 *
                 *  2022-12-02 新的服务工单未完成超时增加了72h、96h、360h超时时间段
                 *  Function	25	未完成工单96小时提醒
                 *  Function	26	未完成工单360小时提醒
                 *
                 */
                if (!hasNotified(orderId, function)) {
                    // 未存在通知记录，发送通知
                    orderMap.put("Function", function);
                    overTimeOrderList.add(orderMap);
                }
            }

            /**
             * 遍历已经触发了超时时间的服务工单
             */
            if (CollectionUtils.isNotEmpty(overTimeOrderList)) {
                for (Map<String, Object> overTimeOrder : overTimeOrderList) {
                    // 超时订单
                    Integer category = 2;
                    // 通知类型
                    Integer function = MapUtils.getInteger(overTimeOrder, "Function");
                    // 工单信息
                    Long orderId = MapUtils.getLong(overTimeOrder, "ID");
                    Long serviceStationId = MapUtils.getLong(overTimeOrder, "ServiceStationId");
                    String orderNo = MapUtils.getString(overTimeOrder, "OrderNo");

                    // function = 14 表示：当前服务工单在24小时之内未完成服务工单
                    if (function == 14) {
                        setOverTimeKey(orderId, OverTimeType.TYPE7);
                    }

                    /**
                     * 根据当前服务工单查询出对应的区域工程师
                     * 在由区域工程师查询出区域工程师所关联的消息接收人(此功能在web页面进行关系绑定)
                     */
                    // 查询超时4/6/12/24/48/72/96/360小时通知人员
                    List<Map<String, Object>> sendList = getNotifyAreaEngineerList(orderId, orderNo, function, overTimeOrder);
                    // 发送相关人员
                    if (CollectionUtils.isNotEmpty(sendList)) {
                        //获取 区域工程师，站长，技师
                        List<Map<String, Object>> sendUserList = this.getSendUserList(orderId, serviceStationId);
                        //将查询的结果合并
                        sendUserList.addAll(sendList);
                        Set<String> sendSet = new HashSet<>(sendUserList.size());
                        for (Map<String, Object> senderMap : sendUserList) {
                            String phone = MapUtils.getString(senderMap, "Phone");
                            String username = MapUtils.getString(senderMap, "UserName");
                            log.info("DBU-sendList--开始" + phone + "-" + username);
                            String userId = MapUtils.getString(senderMap, "ID");
                            if (sendSet.contains(phone)) {
                                continue;
                            } else {
                                sendSet.add(phone);
                            }
                            sendMsgForUnfinishedWorkOrder(phone, orderNo, username, orderId, userId, function, category, overTimeOrder, senderMap.containsKey("textNew"));
                        }
                    }
                }
            }
        }
    }

    @Override
    /**
     * @param userT 用户信息
     * @param esn 发动机信息
     * @param activeService 用户签署状态
     * @author yixuan Ding
     * @apiNote sprint26需求 同步用户签署或解除状态及设备列表
     * @since 2021-12-09
     * */
    public void syncServiceAgreementAndEngineToCRM(UserT userT, String esn, Boolean activeService,Boolean flag) {
        AccountEngineRelaRequest accountEngineRelaRequest = new AccountEngineRelaRequest();
        if (esn == null) {//同步用户签署或解除状态及设备列表
            convertRequest(userT, activeService, accountEngineRelaRequest);
        } else {
            convertRequest(userT, esn, activeService, accountEngineRelaRequest,flag);
        }
        CRMApiUtils.getCRMServiceApi().syncServiceAgreementAndEngineToCRM(accountEngineRelaRequest);
    }

    @Override
    public void syncUserInfoToCRM(UserT userT, Boolean activeService) {
        AccountEngineRelaRequest accountEngineRelaRequest = new AccountEngineRelaRequest();
        AgreementSigned agreementSigned = setAgreementSigned(userT, activeService, accountEngineRelaRequest);
        List<AgreementSigned.EsnMap> engine = new ArrayList<>();
        agreementSigned.setEngine(engine);
        List<AgreementSigned> data = new ArrayList<>();
        data.add(agreementSigned);
        accountEngineRelaRequest.setData(data);
        CRMApiUtils.getCRMServiceApi().syncServiceAgreementAndEngineToCRM(accountEngineRelaRequest);
    }

    private void convertRequest(UserT userT, Boolean activeService, AccountEngineRelaRequest accountEngineRelaRequest) {
        AgreementSigned agreementSigned = setAgreementSigned(userT, activeService, accountEngineRelaRequest);
        Map<String, Object> map = new HashMap<>();
        map.put("userId", userT.getId());
        List<Map<String, Object>> customerEngineRelList = customerEngineRelDao.getCustomerEngineRelList(map);
        List<AgreementSigned.EsnMap> engine = new ArrayList<>();
        List<AgreementSigned> data = new ArrayList<>();
        if (activeService) {//签署服务需要将设备列表一同同步，解除服务只需要将activeService = false即可
            for (Map<String, Object> customerMap : customerEngineRelList) {
                AgreementSigned.EsnMap esnMap = new AgreementSigned.EsnMap();
                String esn = MapUtils.getString(customerMap, "ESN");
                esnMap.setESN(esn);
                esnMap.setStatus("Active");
                engine.add(esnMap);
            }
            agreementSigned.setEngine(engine);
        }
        data.add(agreementSigned);
        accountEngineRelaRequest.setData(data);

    }

    private void convertRequest(UserT userT, String esn, Boolean activeService, AccountEngineRelaRequest accountEngineRelaRequest,Boolean flag) {
        AgreementSigned agreementSigned = setAgreementSigned(userT, activeService, accountEngineRelaRequest);
        List<AgreementSigned.EsnMap> engine = new ArrayList<>();
        List<AgreementSigned> data = new ArrayList<>();
        if (flag) {//添加设备
            AgreementSigned.EsnMap esnMap = new AgreementSigned.EsnMap();
            esnMap.setESN(esn);
            esnMap.setStatus("Active");
            engine.add(esnMap);
            agreementSigned.setEngine(engine);
        }else{
            AgreementSigned.EsnMap esnMap = new AgreementSigned.EsnMap();
            esnMap.setESN(esn);
            engine.add(esnMap);
            agreementSigned.setEngine(engine);
        }
        data.add(agreementSigned);
        accountEngineRelaRequest.setData(data);
    }

    private AgreementSigned setAgreementSigned(UserT userT, Boolean activeService, AccountEngineRelaRequest accountEngineRelaRequest) {
        AgreementSigned agreementSigned = new AgreementSigned();
        long currentTimeMillis = System.currentTimeMillis();
        String masNumber = AESTool.encryptString(currentTimeMillis + "" + userT.getId());
        accountEngineRelaRequest.setMasNumber(masNumber);
        agreementSigned.setName(userT.getContact());
        agreementSigned.setADUserID(String.valueOf(userT.getId()));
        agreementSigned.setUserName(userT.getUserName());
        agreementSigned.setActiveService(activeService);
        agreementSigned.setMobilePhone(userT.getServicePhone());
        agreementSigned.setRegistMobilePhone(userT.getPhone());
        return agreementSigned;
    }

    public void setOverTimeKey(Long orderId, OverTimeType overTimeType) {
        String workOrderId = String.valueOf(orderId);
        Integer code = overTimeType.getCode();
        redisClientUtils.setObject(RedisKeys.overTimeWorkOrderTypeKey(workOrderId, code), code, 60 * 60 * 24 * 30);
    }

    public List<Map<String, Object>> getNotifyAreaEngineerList(Long orderId, String orderNo, Integer function, Map<String, Object> overTimeOrder) {
        List<Map<String, Object>> areaEngineerList = new ArrayList<>();
        /**
         * 查询出当前服务工单对应的区域工程师
         */
        Map<String, Object> areaEngineerMap = workOrderOperatorRelationDao.getOperatorByOrderId(orderId);
        Map<String, Object> workOrderMap = workOrderTDao.getOrderById(orderId);

        /**
         * 如果没有区域工程师
         * 1：保存错误信息记录
         * 2：同步工单超时到crm
         */
        if (org.apache.commons.collections.MapUtils.isEmpty(areaEngineerMap)) {
            log.error("获取未完成工单区域工程师信息异常，区域工程师信息为空，orderId：" + orderId);
            saveErrorNotify(overTimeOrder, function, 2, "区域工程师信息为空");
            notifyCRM(function, overTimeOrder, new HashMap<>());
            return areaEngineerList;
        }

        String phone = org.apache.commons.collections.MapUtils.getString(areaEngineerMap, "Phone");
        String name = org.apache.commons.collections.MapUtils.getString(areaEngineerMap, "Name");
        String crmPositionName = org.apache.commons.collections4.MapUtils.getString(areaEngineerMap, "CrmPositionName");
        String marketType = org.apache.commons.collections.MapUtils.getString(workOrderMap, "MarketType");
        Long channelId = org.apache.commons.collections.MapUtils.getLong(workOrderMap, "OrderChannel");

        log.info("DBU-areaEngineerMap--开始" + phone +"-"+name);


        /**
         * 如果区域工程师手机号为空
         * 只同步工单超时信息到crm
         */
        if (StringUtils.isEmpty(phone)) {
            log.error("获取工程师相关信息失败：工程师手机号为空，phone：" + phone);
            notifyCRM(function, overTimeOrder, new HashMap<>());
            return areaEngineerList;
        }

        // 发送crm超时通知信息
        Map<String, Object> domainInfoMap = dbuRemindTaskTDao.getDomainInfoByPhone(phone, channelId, crmPositionName, marketType);
        if (org.apache.commons.collections.MapUtils.isNotEmpty(domainInfoMap)) {
            notifyCRM(function, overTimeOrder, domainInfoMap);
        } else {
            log.error("超时未完成工单拼装区域信息失败，查无区域信息，工程师手机号：" + phone);
            notifyCRM(function, overTimeOrder, new HashMap<>());
            saveErrorNotify(overTimeOrder, function, 2, "查无区域信息，工程师手机号：" + phone);
        }

        /**
         * 查询出当前区域工程师所关联的消息接收人
         */
        List<Map<String, Object>> notifyEngineerListMap = overTimeNotifyAreaEngineerDao.getNotifyEngineerListByAreaEngineer(phone);
        if (org.apache.commons.collections.CollectionUtils.isEmpty(notifyEngineerListMap)) {
            log.error("获取24/48小时未完成工单通知人员信息异常，区域工程师手机号：" + phone + "；姓名：" + name);
            saveErrorNotify(overTimeOrder, function, 2, "获取24/48小时未完成工单通知人员信息异常，区域工程师手机号：" + phone + "；姓名：" + name);
            return areaEngineerList;
        }

        /**
         * function参数说明：
         *	Function	21	未完成工单4小时提醒
         *	Function	22	未完成工单6小时提醒
         *	Function	23	未完成工单12小时提醒
         *  Function	14	未完成工单24小时提醒
         *	Function	15	未完成工单48小时提醒
         *	Function	24	未完成工单72小时提醒
         *
         * 2022-12-02 新增：
         *	Function	25	未完成工单96小时提醒
         *	Function	26	未完成工单360小时提醒
         */
        List<Integer> typeList = new ArrayList<Integer>();
        // 根据通知类型拼装通知人员
        switch (function) {
            case 26:
                // 当区域工程师下没有配置96小时或360小时 时 不能发短息，如果有一个或多个配置则可以发
                for (Map<String, Object> notifyEngineerTypeMap : notifyEngineerListMap) {
                    Integer type = org.apache.commons.collections.MapUtils.getInteger(notifyEngineerTypeMap, "Type");
                    typeList.add(type);
                }
                if (typeList == null || typeList.size() <= 0) {
                    break;
                }
                if (!typeList.contains(9)) {
                    break;
                }
                // 360小时通知人员 96小时通知人员 72小时通知人员 48小时通知人员 24小时通知人员 12小时通知人员 6小时通知人员 以及 4小时通知人员
                for (Map<String, Object> notifyEngineerMap : notifyEngineerListMap) {

                    Map<String, Object> threeHundredSixMap = new HashMap<>(5);
                    threeHundredSixMap.put("Contact", org.apache.commons.collections.MapUtils.getString(notifyEngineerMap, "ProcessorName"));
                    String threeHundredSixPhone = org.apache.commons.collections.MapUtils.getString(notifyEngineerMap, "ProcessorPhone");
                    if (StringUtils.isNotEmpty(threeHundredSixPhone)) {
                        List<UserT> userTList = loginDao.getUserByPhone(threeHundredSixPhone);
                        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(userTList)) {
                            threeHundredSixMap.put("ID", userTList.get(0).getId());
                            threeHundredSixMap.put("UserName", userTList.get(0).getUserName());
                        }
                        threeHundredSixMap.put("Phone", threeHundredSixPhone);
                        areaEngineerList.add(threeHundredSixMap);
                    }
                }
                break;
            case 25:
                // 当区域工程师下没有配置96小时或360小时 时 不能发短息，如果有一个或多个配置则可以发
                for (Map<String, Object> notifyEngineerTypeMap : notifyEngineerListMap) {
                    Integer type = org.apache.commons.collections.MapUtils.getInteger(notifyEngineerTypeMap, "Type");
                    typeList.add(type);
                }
                if (typeList == null || typeList.size() <= 0) {
                    break;
                }
                if (!typeList.contains(8)) {
                    break;
                }
                // 96小时通知人员 72小时通知人员 48小时通知人员 24小时通知人员 12小时通知人员 6小时通知人员 以及 4小时通知人员
                for (Map<String, Object> notifyEngineerMap : notifyEngineerListMap) {
                    Integer type = org.apache.commons.collections.MapUtils.getInteger(notifyEngineerMap, "Type");
                    if (type.equals(8) || type.equals(7) || type.equals(3) || type.equals(2) || type.equals(4) || type.equals(5) || type.equals(6)) {
                        Map<String, Object> ninetySixMap = new HashMap<>(5);
                        ninetySixMap.put("Contact", org.apache.commons.collections.MapUtils.getString(notifyEngineerMap, "ProcessorName"));
                        String ninetySixPhone = org.apache.commons.collections.MapUtils.getString(notifyEngineerMap, "ProcessorPhone");
                        if (StringUtils.isNotEmpty(ninetySixPhone)) {
                            List<UserT> userTList = loginDao.getUserByPhone(ninetySixPhone);
                            if (org.apache.commons.collections.CollectionUtils.isNotEmpty(userTList)) {
                                ninetySixMap.put("ID", userTList.get(0).getId());
                                ninetySixMap.put("UserName", userTList.get(0).getUserName());
                            }
                            ninetySixMap.put("Phone", ninetySixPhone);
                            areaEngineerList.add(ninetySixMap);
                        }
                    }
                }
                break;
            case 24:
                /**
                 * type说明：
                 * 		type值表示当前消息接收人只接收指定超时的消息
                 * 		比如：type=4 表示当前消息接收人，只接收4小时未完成的消息提醒
                 *         4:表示4小时未完成超时推送类型
                 *         1:表示8小时未完成超时推送类型
                 *         2:表示24小时未完成超时推送类型
                 *         3:表示48小时未完成超时推送类型
                 *         新需求后增加了几个类型
                 *         5:表示6小时未完成超时推送类型
                 *         6:表示12小时未完成超时推送类型
                 *         7:表示72小时未完成超时推送类型
                 *
                 *         2022-12-02 新增：
                 *         8:表示96小时未完成超时推送类型
                 *         9:表示360小时未完成超时推送类型
                 */
                // 72小时通知人员 48小时通知人员 24小时通知人员 12小时通知人员 6小时通知人员 以及 4小时通知人员
                for (Map<String, Object> notifyEngineerMap : notifyEngineerListMap) {
                    Integer type = org.apache.commons.collections.MapUtils.getInteger(notifyEngineerMap, "Type");
                    if (type.equals(7) || type.equals(3) || type.equals(2) || type.equals(4) || type.equals(5) || type.equals(6)) {
                        Map<String, Object> twentyFourMap = new HashMap<>(5);
                        twentyFourMap.put("Contact", org.apache.commons.collections.MapUtils.getString(notifyEngineerMap, "ProcessorName"));
                        String twentyFourPhone = org.apache.commons.collections.MapUtils.getString(notifyEngineerMap, "ProcessorPhone");
                        /**
                         * 此块逻辑
                         * 根据手机号从User_T表中查询出用户信息
                         * 但用户在当前系统可能是不存在的，仍需要推送短信
                         */
                        if (StringUtils.isNotEmpty(twentyFourPhone)) {
                            List<UserT> userTList = loginDao.getUserByPhone(twentyFourPhone);
                            if (org.apache.commons.collections.CollectionUtils.isNotEmpty(userTList)) {
                                twentyFourMap.put("ID", userTList.get(0).getId());
                                twentyFourMap.put("UserName", userTList.get(0).getUserName());
                            }
                            twentyFourMap.put("Phone", twentyFourPhone);
                            areaEngineerList.add(twentyFourMap);
                        }
                    }
                }
                break;
            case 15:
                // 48小时通知人员 24小时通知人员 12小时通知人员 6小时通知人员 以及 4小时通知人员
                for (Map<String, Object> notifyEngineerMap : notifyEngineerListMap) {

                    Integer type = org.apache.commons.collections.MapUtils.getInteger(notifyEngineerMap, "Type");
                    if (type.equals(3) || type.equals(2) || type.equals(4) || type.equals(5) || type.equals(6)) {
                        Map<String, Object> fortyEightMap = new HashMap<>(5);
                        fortyEightMap.put("Contact", org.apache.commons.collections.MapUtils.getString(notifyEngineerMap, "ProcessorName"));
                        String fortyEightPhone = org.apache.commons.collections.MapUtils.getString(notifyEngineerMap, "ProcessorPhone");
                        List<UserT> userT1List = loginDao.getUserByPhone(fortyEightPhone);
                        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(userT1List)) {
                            fortyEightMap.put("ID", userT1List.get(0).getId());
                            fortyEightMap.put("UserName", userT1List.get(0).getUserName());
                        }
                        fortyEightMap.put("Phone", fortyEightPhone);
                        areaEngineerList.add(fortyEightMap);
                    }
                }
                break;
            case 14:
                // 24小时通知人员 12小时通知人员 6小时通知人员 以及 4小时通知人员
                for (Map<String, Object> notifyEngineerMap : notifyEngineerListMap) {
                    Integer type = org.apache.commons.collections.MapUtils.getInteger(notifyEngineerMap, "Type");
                    if (type.equals(2) || type.equals(4) || type.equals(5) || type.equals(6)) {
                        Map<String, Object> twentyFourMap = new HashMap<>(5);
                        twentyFourMap.put("Contact", org.apache.commons.collections.MapUtils.getString(notifyEngineerMap, "ProcessorName"));
                        String twentyFourPhone = org.apache.commons.collections.MapUtils.getString(notifyEngineerMap, "ProcessorPhone");
                        if (StringUtils.isNotEmpty(twentyFourPhone)) {
                            List<UserT> userTList = loginDao.getUserByPhone(twentyFourPhone);
                            if (org.apache.commons.collections.CollectionUtils.isNotEmpty(userTList)) {
                                twentyFourMap.put("ID", userTList.get(0).getId());
                                twentyFourMap.put("UserName", userTList.get(0).getUserName());
                            }
                            twentyFourMap.put("Phone", twentyFourPhone);
                            areaEngineerList.add(twentyFourMap);
                        }
                    }
                }
                break;
            case 23:
                // 12小时通知人员 6小时通知人员 以及 4小时通知人员
                for (Map<String, Object> notifyEngineerMap : notifyEngineerListMap) {
                    Integer type = org.apache.commons.collections.MapUtils.getInteger(notifyEngineerMap, "Type");
                    if (type.equals(4) || type.equals(5) || type.equals(6)) {
                        Map<String, Object> fiveMap = new HashMap<>(5);
                        fiveMap.put("Contact", org.apache.commons.collections.MapUtils.getString(notifyEngineerMap, "ProcessorName"));
                        String fivePhone = org.apache.commons.collections.MapUtils.getString(notifyEngineerMap, "ProcessorPhone");
                        List<UserT> userT1List = loginDao.getUserByPhone(fivePhone);
                        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(userT1List)) {
                            fiveMap.put("ID", userT1List.get(0).getId());
                            fiveMap.put("UserName", userT1List.get(0).getUserName());
                        }
                        fiveMap.put("Phone", fivePhone);
                        areaEngineerList.add(fiveMap);
                    }
                }
                break;
            case 22:
                // 6小时通知人员 以及 4小时通知人员
                for (Map<String, Object> notifyEngineerMap : notifyEngineerListMap) {
                    Integer type = org.apache.commons.collections.MapUtils.getInteger(notifyEngineerMap, "Type");
                    if (type.equals(4) || type.equals(5)) {
                        Map<String, Object> fiveMap = new HashMap<>(5);
                        fiveMap.put("Contact", org.apache.commons.collections.MapUtils.getString(notifyEngineerMap, "ProcessorName"));
                        String fivePhone = org.apache.commons.collections.MapUtils.getString(notifyEngineerMap, "ProcessorPhone");
                        List<UserT> userT1List = loginDao.getUserByPhone(fivePhone);
                        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(userT1List)) {
                            fiveMap.put("ID", userT1List.get(0).getId());
                            fiveMap.put("UserName", userT1List.get(0).getUserName());
                        }
                        fiveMap.put("Phone", fivePhone);
                        areaEngineerList.add(fiveMap);
                    }
                }
                break;
            case 21:
                // 4小时通知人员
                for (Map<String, Object> notifyEngineerMap : notifyEngineerListMap) {
                    Integer type = org.apache.commons.collections.MapUtils.getInteger(notifyEngineerMap, "Type");
                    if (type.equals(4)) {
                        Map<String, Object> fiveMap = new HashMap<>(5);
                        fiveMap.put("Contact", org.apache.commons.collections.MapUtils.getString(notifyEngineerMap, "ProcessorName"));
                        String fivePhone = org.apache.commons.collections.MapUtils.getString(notifyEngineerMap, "ProcessorPhone");
                        List<UserT> userT1List = loginDao.getUserByPhone(fivePhone);
                        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(userT1List)) {
                            fiveMap.put("ID", userT1List.get(0).getId());
                            fiveMap.put("UserName", userT1List.get(0).getUserName());
                        }
                        fiveMap.put("Phone", fivePhone);
                        areaEngineerList.add(fiveMap);
                    }
                }
                break;
            default:
                break;
        }
        //去重
        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(areaEngineerList)) {
            Set<String> set = new HashSet<>();
            areaEngineerList = areaEngineerList.stream().filter(e -> {
                String phoneSet = (String) e.get("Phone");
                return set.add(phoneSet);
            }).collect(Collectors.toList());
        }
        return areaEngineerList;
    }

    /**
     * 查询区域工程师   站长 和 技师
     *
     * @param orderId
     * @return
     */
    public List<Map<String, Object>> getSendUserList(Long orderId, Long serviceStationId) {

        List<Map<String, Object>> areaEngineerListNew = new ArrayList<>();

        //区域工程师
        //管辖关系工程师
        List<UserT> userListByServiceStationIdCompanyId = positionUserTDao.getUserListByServiceStationIdCompanyId(1L, serviceStationId);
        if (CollectionUtils.isNotEmpty(userListByServiceStationIdCompanyId)) {
            for (UserT userT : userListByServiceStationIdCompanyId) {
                Map<String, Object> fiveMap = new HashMap<>(5);
                fiveMap.put("Contact", userT.getContact());
                fiveMap.put("ID", userT.getId());
                fiveMap.put("UserName", userT.getUserName());
                fiveMap.put("textNew", true);
                fiveMap.put("Phone", userT.getPhone());
                areaEngineerListNew.add(fiveMap);
            }
        }
        //400指派的工程师
        Map<String, Object> operatorByOrderId = workOrderOperatorRelationDao.getOperatorUserIdByOrderId(orderId);
        if (null != operatorByOrderId && operatorByOrderId.containsKey("userId")) {
            Map<String, Object> fiveMap = new HashMap<>(5);
            UserT userId = userTDao.selectById(org.apache.commons.collections.MapUtils.getLong(operatorByOrderId, "userId"));
            if (userId != null) {
                fiveMap.put("Contact", org.apache.commons.collections.MapUtils.getString(operatorByOrderId, "name"));
                fiveMap.put("ID", org.apache.commons.collections.MapUtils.getLong(operatorByOrderId, "userId"));
                fiveMap.put("UserName", userId.getUserName());
                fiveMap.put("textNew", true);
                fiveMap.put("Phone", org.apache.commons.collections.MapUtils.getString(operatorByOrderId, "phone"));
                areaEngineerListNew.add(fiveMap);
            }
        }
        //查询 站长
        List<UserT> stationMasterByWorkOrderId = userTDao.getStationMasterByWorkOrderId(orderId);
        if (CollectionUtils.isNotEmpty(stationMasterByWorkOrderId)) {
            for (UserT userT : stationMasterByWorkOrderId) {
                Map<String, Object> fiveMap = new HashMap<>(5);
                fiveMap.put("Contact", userT.getContact());
                fiveMap.put("ID", userT.getId());
                fiveMap.put("UserName", userT.getUserName());
                fiveMap.put("textNew", true);
                fiveMap.put("Phone", userT.getPhone());
                areaEngineerListNew.add(fiveMap);
            }
        }
        //查询 主技师 只有一位
        WorkOrderT workOrderTByOrderId = workOrderTDao.getWorkOrderTByOrderId(orderId);
        List<UserT> userTStationIdAndOrderId = userTDao.getUserTStationIdAndOrderId(workOrderTByOrderId.getServiceStationId(), orderId);
        if (CollectionUtils.isNotEmpty(userTStationIdAndOrderId)) {
            UserT userT = userTStationIdAndOrderId.get(0);
            Map<String, Object> fiveMap = new HashMap<>(5);
            fiveMap.put("Contact", userT.getContact());
            fiveMap.put("ID", userT.getId());
            fiveMap.put("UserName", userT.getUserName());
            fiveMap.put("textNew", true);
            fiveMap.put("Phone", userT.getPhone());
            areaEngineerListNew.add(fiveMap);
        }
        return areaEngineerListNew;
    }

    private void notifyCRM(Integer function, Map<String, Object> overTimeOrder, Map<String, Object> domainInfoMap) {
        Map<String, Object> getNotifyCrmMap = new HashMap<>();
        getNotifyCrmMap.put("orderNo", org.apache.commons.collections.MapUtils.getString(overTimeOrder, "OrderNo"));
        getNotifyCrmMap.put("CRMOrderNo", org.apache.commons.collections.MapUtils.getString(overTimeOrder, "OrderNoCrm"));
        getNotifyCrmMap.put("domainId", org.apache.commons.collections.MapUtils.getString(domainInfoMap, "CrmPostNo", ""));
        getNotifyCrmMap.put("domainName", org.apache.commons.collections.MapUtils.getString(domainInfoMap, "CrmPositionName", ""));
        getNotifyCrmMap.put("operatorName", "系统");
        getNotifyCrmMap.put("operatorPhone", "18501075230");
        /**
         * function参数说明：
         *	Function	21	未完成工单4小时提醒
         *	Function	22	未完成工单6小时提醒
         *	Function	23	未完成工单12小时提醒
         *  Function	14	未完成工单24小时提醒
         *	Function	15	未完成工单48小时提醒
         *	Function	24	未完成工单72小时提醒
         *
         * 2022-12-02 新增：
         *	Function	25	未完成工单96小时提醒
         *	Function	26	未完成工单360小时提醒
         */
        switch (function) {
            case 26:
                getNotifyCrmMap.put("timeOut", "360h");
                break;
            case 25:
                getNotifyCrmMap.put("timeOut", "96h");
                break;
            case 24:
                getNotifyCrmMap.put("timeOut", "72h");
                break;
            case 15:
                getNotifyCrmMap.put("timeOut", "48h");
                break;
            case 14:
                getNotifyCrmMap.put("timeOut", "24h");
                break;
            case 23:
                getNotifyCrmMap.put("timeOut", "12h");
                break;
            case 22:
                getNotifyCrmMap.put("timeOut", "6h");
                break;
            case 21:
                getNotifyCrmMap.put("timeOut", "4h");
                break;
            default:
                break;
        }
        getNotifyCrmMap.put("systemTime", LocalTimeUtil.getRealCurrentTime());
        CRMResponeEntity responseEntity = CRMApiUtils.getCRMServiceApi().syncTimeoutAccomplish("CCI", getNotifyCrmMap);
        log.info("4/6/12/24/48/72/96/360小时未完成工单通知crm返回值：" + JsonUtils.toJsonString(responseEntity));
        if (responseEntity.getStatus() != 0) {
            log.error("4/6/12/24/48/72/96/360小时未完成工单通知crm失败，响应状态：" + responseEntity.getStatus() + "，响应信息:" + responseEntity.getMessage());
        }
    }

    private void saveErrorNotify(Map<String, Object> overTimeOrder, int function, int category, String exceptionInfo) {
        Long orderId = org.apache.commons.collections.MapUtils.getLong(overTimeOrder, "ID");
        String orderNo = org.apache.commons.collections.MapUtils.getString(overTimeOrder, "OrderNo");

        List<Map<String, Object>> notifyList = new ArrayList<>();
        /**
         * 拼接发送的消息内容
         *  function参数说明：
         *		Function	21	未完成工单4小时提醒
         *		Function	22	未完成工单6小时提醒
         *		Function	23	未完成工单12小时提醒
         *      Function	14	未完成工单24小时提醒
         *		Function	15	未完成工单48小时提醒
         *		Function	24	未完成工单72小时提醒
         *	2022-12-02 新增：
         *		Function	25	未完成工单96小时提醒
         *		Function	26	未完成工单360小时提醒
         *
         */
        String smsText = "";
        switch (function) {
            case 26:
                // 360小时超时
                smsText = dbuMessageService.getUpgradeMessageForUnfinishedWorkOrder(360, overTimeOrder);
                break;
            case 25:
                // 96小时超时
                smsText = dbuMessageService.getUpgradeMessageForUnfinishedWorkOrder(96, overTimeOrder);
                break;
            case 24:
                // 72小时超时
                smsText = dbuMessageService.getUpgradeMessageForUnfinishedWorkOrder(72, overTimeOrder);
                break;
            case 15:
                // 48小时超时
                smsText = dbuMessageService.getUpgradeMessageForUnfinishedWorkOrder(48, overTimeOrder);
                break;
            case 14:
                // 24小时超时
                smsText = dbuMessageService.getUpgradeMessageForUnfinishedWorkOrder(24, overTimeOrder);
                break;
            case 23:
                // 12小时超时
                smsText = dbuMessageService.getUpgradeMessageForUnfinishedWorkOrder(12, overTimeOrder);
                break;
            case 22:
                // 6小时超时
                smsText = dbuMessageService.getUpgradeMessageForUnfinishedWorkOrder(6, overTimeOrder);
                break;
            case 21:
                // 4小时超时
                smsText = dbuMessageService.getUpgradeMessageForUnfinishedWorkOrder(4, overTimeOrder);
                break;
            default:
                smsText = "您有未处理工单，工单号" + orderNo + "，工单已超时，请尽快处理。";
                break;
        }

        Map<String, Object> notifyRecordTMap = new HashMap<>();
        //获取当前时间
        String currentTime = LocalTimeUtil.getRealCurrentTime();
        notifyRecordTMap.put("OrderId", orderId);
        notifyRecordTMap.put("Function", function);
        notifyRecordTMap.put("Category", category);
        // 消息内容
        notifyRecordTMap.put("Content", smsText);
        //推送方式1代表短信  2代表app推送
        notifyRecordTMap.put("SendType", 1);
        notifyRecordTMap.put("SendTime", currentTime);
        notifyRecordTMap.put("Status", 0);
        notifyRecordTMap.put("ExceptionInfo", exceptionInfo);
        notifyRecordTMap.put("IsRead", 0);
        notifyRecordTMap.put("Flag", 0);
        notifyRecordTMap.put("Creator", "");
        notifyRecordTMap.put("CreateTime", currentTime);
        notifyList.add(notifyRecordTMap);

        Map<String, Object> notifyRecordT2Map = new HashMap<>();
        notifyRecordT2Map.put("OrderId", orderId);
        notifyRecordT2Map.put("Function", function);
        notifyRecordT2Map.put("Category", category);
        // 消息内容
        notifyRecordT2Map.put("Content", smsText);
        //推送方式1代表短信  2代表app推送
        notifyRecordT2Map.put("SendType", 2);
        notifyRecordT2Map.put("SendTime", currentTime);
        notifyRecordT2Map.put("Status", 0);
        notifyRecordT2Map.put("ExceptionInfo", exceptionInfo);
        notifyRecordT2Map.put("IsRead", 0);
        notifyRecordT2Map.put("Flag", 0);
        notifyRecordT2Map.put("Creator", "");
        notifyRecordT2Map.put("CreateTime", currentTime);
        notifyList.add(notifyRecordT2Map);

        remindTaskService.saveMsgOperation(notifyList);
    }

    public Boolean hasNotified(Long orderId, Integer function) {
        Boolean notified = Boolean.TRUE;
        Map<String, Object> queryNotify = new HashMap<>();
        queryNotify.put("OrderId", orderId);
        queryNotify.put("Function", function);
        List<Map<String, Object>> notifyList = notifyRecordTDao.selectOrderRecordList(queryNotify);
        if (org.apache.commons.collections.CollectionUtils.isEmpty(notifyList)) {
            notified = Boolean.FALSE;
        } else {
            if (function.equals(17)) {
                Map<String, Object> notifyMap = notifyList.get(0);
                String createTime = org.apache.commons.collections.MapUtils.getString(notifyMap, "CreateTime");
                long durationMinutes = LocalTimeUtil.getDurationMinutes(createTime, LocalTimeUtil.getRealCurrentTime());
                if (durationMinutes >= 24 * 60L) {
                    notified = Boolean.FALSE;
                }
            }
        }
        return notified;
    }

    public void sendMsgForUnfinishedWorkOrder(String phone, String orderNo, String userName, Long orderId, String userId, int function, int category, Map<String, Object> overTimeOrder, boolean textNewFlag) {
        List<Map<String, Object>> notifyRecordTMapList = new ArrayList<>();

        String smsText = "";
        switch (function) {
            case 26:
                // 360小时超时
                smsText = dbuMessageService.getUpgradeMessageForUnfinishedWorkOrder(360, overTimeOrder);
                break;
            case 25:
                // 96小时超时
                smsText = dbuMessageService.getUpgradeMessageForUnfinishedWorkOrder(96, overTimeOrder);
                break;
            case 24:
                // 72小时超时
                smsText = dbuMessageService.getUpgradeMessageForUnfinishedWorkOrder(72, overTimeOrder);
                break;
            case 15:
                // 48小时超时
                smsText = dbuMessageService.getUpgradeMessageForUnfinishedWorkOrder(48, overTimeOrder);
                break;
            case 14:
                // 24小时超时
                smsText = dbuMessageService.getUpgradeMessageForUnfinishedWorkOrder(24, overTimeOrder);
                break;
            case 23:
                // 12小时超时
                smsText = dbuMessageService.getUpgradeMessageForUnfinishedWorkOrder(12, overTimeOrder);
                break;
            case 22:
                // 6小时超时
                smsText = dbuMessageService.getUpgradeMessageForUnfinishedWorkOrder(6, overTimeOrder);
                break;
            case 21:
                // 4小时超时
                smsText = dbuMessageService.getUpgradeMessageForUnfinishedWorkOrder(4, overTimeOrder);
                break;
            default:
                smsText = "您有未处理工单，工单号" + orderNo + "，工单已超时，请尽快处理。";
                break;
        }

        log.info("DBU-sendMsgForUnfinishedWorkOrder--开始" + phone +"-"+smsText);

        smsText = textNewFlag ? smsText + VR_TIMEOUT_TEXT : smsText;
        //短信发送
        if (StringUtils.isNotEmpty(phone)) {
            // 发送短信操作
            String sendResult = SmsUtils.sendMessage(phone, smsText);
            // 拼装入库记录信息
            Map<String, Object> map = getMsgMap(orderId, smsText, userId, 1, function, category, 1);

            // "00"状态码表示短信发送成功
            if (!"00".equals(sendResult)) {
                map.put("Status", 0);
                map.put("ExceptionInfo", String.format("短信发送失败 手机号:%s 状态码:%s", phone, sendResult));
            } else {
                map.put("ExceptionInfo", String.format("短信发送成功 手机号:%s", phone));
            }

            notifyRecordTMapList.add(map);
        }

        // 将发送记录列表存入数据库
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(notifyRecordTMapList)) {
            remindTaskService.saveMsgOperation(notifyRecordTMapList);
        }
        // 发送推送
        if (null != userId && NumberUtils.isNumber(userId)) {
            noticeService.push(function, category, orderId, Long.valueOf(userId), userName, null, smsText, "您有未处理工单", 0L);
        } else {
            noticeService.push(function, category, orderId, null, userName, null, smsText, "您有未处理工单", 0L);
        }
    }

    public Map<String, Object> getMsgMap(Long orderId, String smsText, String userId, int SendType, int function, int category, int status) {
        return getMsgMap(orderId, smsText, userId, SendType, function, category, status, "");
    }

    public Map<String, Object> getMsgMap(Long orderId, String smsText, String userId, int SendType, int function, int category, int status, String exceptionInfo) {
        Map<String, Object> notifyRecordTMap = new HashMap<>();
        //获取当前时间
        String currentTime = LocalTimeUtil.getRealCurrentTime();
        notifyRecordTMap.put("OrderId", orderId);
        notifyRecordTMap.put("Function", function);
        notifyRecordTMap.put("Category", category);
        //接收人
        notifyRecordTMap.put("ReceiverId", StringUtils.isEmpty(userId) ? null : Long.parseLong(userId));
        // 消息内容
        notifyRecordTMap.put("Content", smsText);
        //推送方式1代表短信  2代表app推送
        notifyRecordTMap.put("SendType", SendType);
        notifyRecordTMap.put("SendTime", currentTime);
        notifyRecordTMap.put("Status", status);
        notifyRecordTMap.put("ExceptionInfo", StringUtils.isEmpty(exceptionInfo) ? "" : exceptionInfo);
        notifyRecordTMap.put("IsRead", 0);
        notifyRecordTMap.put("Flag", 0);
        notifyRecordTMap.put("Creator", "");
        notifyRecordTMap.put("CreateTime", currentTime);
        return notifyRecordTMap;
    }

}
